﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Linq;
using AutoMapper;
using Mehdime.Entity;
using WikeSoft.Core;
using WikeSoft.Core.Exception;
using WikeSoft.Data.Enum;
using WikeSoft.Enterprise.Entities;
using WikeSoft.Enterprise.Interfaces;
using WikeSoft.Enterprise.Interfaces.Sys;
using WikeSoft.Enterprise.Interfaces.WorkFlow;
using WikeSoft.Enterprise.Models;
using WikeSoft.Enterprise.Models.Filters;

using WikeSoft.Core.Extension;
using WikeSoft.WorkFlowEngine.Enum;
using WikeSoft.WorkFlowEngine.Interfaces;
using WikeSoft.WorkFlowEngine.Models;
using WikeSoft.WorkFlowEngine.Msg;


namespace WikeSoft.Enterprise.AppServices
{
    public class HolidayApplyService : BaseServices, IHolidayApplyService
    {

        private readonly IMapper _mapper;
        private readonly IDbContextScopeFactory _dbContextScopeFactory;
        private readonly IWorkFlowService _workFlowService;
        private readonly IWorkFlowInstanceService _flowInstanceService;
        private readonly IKeyValueService _keyValueService;

        public HolidayApplyService(IMapper mapper, IDbContextScopeFactory dbContextScopeFactory,
             IKeyValueService keyValueService, IWorkFlowService workFlowService, IWorkFlowInstanceService flowInstanceService)
        {
            _mapper = mapper;
            _dbContextScopeFactory = dbContextScopeFactory;

            _keyValueService = keyValueService;
            _workFlowService = workFlowService;
            _flowInstanceService = flowInstanceService;
        }
        public string Add(HolidayModel model)
        {
            using (var context = new WikeDbContext())
            {
                Holiday data = new Holiday()
                {
                    Person = model.Person,
                    StartDate = model.StartDate,
                    UserId = model.UserId,
                    EndDate = model.EndDate,
                    Days = model.Days,
                    Remark = model.Remark,
                    FlowId = model.FlowId,
                    CreateDate = DateTime.Now,

                    Id = Guid.NewGuid().ToString().ToUpper()
                };
                context.Holidays.Add(data);

                context.SaveChanges();

                return data.Id;
            }
        }

        public void Edit(HolidayModel model)
        {
            using (var context = new WikeDbContext())
            {
                var data = context.Holidays.Find(model.Id);
                if (data != null)
                {
                    data.Person = model.Person;
                    data.StartDate = model.StartDate;
                    data.EndDate = model.EndDate;
                    data.Days = model.Days;
                    data.Remark = model.Remark;
                    data.FlowId = model.FlowId;
                }

                context.SaveChanges();
            }
        }

        public HolidayModel Get(string id)
        {
            HolidayModel model = new HolidayModel();
            using (var context = new WikeDbContext())
            {
                var data = context.Holidays.Find(id);
                if (data != null)
                {
                    model.Id = data.Id;
                    model.Person = data.Person;
                    model.StartDate = data.StartDate;
                    model.EndDate = data.EndDate;
                    model.Days = data.Days;
                    model.Remark = data.Remark;
                    model.FlowId = data.FlowId;
                }
            }
            return model;
        }

        public void Delete(IList<string> ids)
        {
            using (var context = new WikeDbContext())
            {
                var data = context.Holidays.Where(c => ids.Contains(c.Id));
                context.Holidays.RemoveRange(data);

                context.SaveChanges();
            }
        }

        public PagedResult<HolidayModel> GetList(HolidayFilter filters)
        {
            using (var context = new WikeDbContext())
            {

                var query = context.Holidays.Where(x => true);
                if (!String.IsNullOrEmpty(filters.keywords))
                {
                    query = query.Where(c => c.Remark.Contains(filters.keywords));
                }
                if (filters.UserId.IsNotBlank())
                {
                    query = query.Where(c => c.UserId == filters.UserId);
                }
                if (filters.FlowIds != null && filters.FlowIds.Count > 0)
                {
                    query = query.Where(c => filters.FlowIds.Contains(c.FlowId));
                }
                var data = query.OrderByCustom(filters.sidx, filters.sord)
                    .Select(item => new HolidayModel
                    {
                        Id = item.Id,
                        Person = item.Person,
                        StartDate = item.StartDate,
                        EndDate = item.EndDate,
                        Days = item.Days,
                        Remark = item.Remark,
                        FlowId = item.FlowId,
                        CreateDate = item.CreateDate
                    }).Paging(filters.page, filters.rows);

                foreach (var holiday in data.rows)
                {
                    if (holiday.FlowId.IsNotBlank())
                    {
                        TaskInstance task = _flowInstanceService.GetRunFlowInstance(holiday.FlowId);
                        holiday.TaskName = task == null ? "已完成" : task.NodeDefName;
                    }
                }

                return data;
            }
        }


        public bool StartWorkFlow(IList<string> ids, string userId)
        {
            using (var scope = _dbContextScopeFactory.Create())
            {
                var db = scope.DbContexts.Get<WikeDbContext>();

                var user = db.SysUsers.Load(userId);

                string flowKey = WorkFlowKey.Holiday;
                WorkFlowAuthority authority = _flowInstanceService.GetFirstNodeAuthority(flowKey, string.Empty);
                var targetUser = _workFlowService.GetAuthorityUser(authority, userId);


                foreach (var id in ids)
                {
                    var data = db.Holidays.Load(id);

                    if (data.FlowId != null)
                    {
                        throw new TipInfoException("不能重复发起退证申请");
                    }
                    var instance = string.Format("{0}请假申请-{1}", user.TrueName, DateTime.Now.ToString("yyyy-MM-dd"));

                    List<WorkFlowAuthority> authorities = _flowInstanceService.GetAuthorities(flowKey);

                    var users = _workFlowService.GetAuthorityUsers(authorities, userId);

                    CreateParms parms = new CreateParms();
                    parms.FlowDefKey = flowKey;
                    parms.UserId = user.Id;
                    parms.UserName = user.TrueName;
                    parms.TargetUserId = targetUser;
                    parms.ObjectId = id.ToString();
                    //parms.remark = "退证原因：" + backCertificateFlow.BackReason;
                    parms.InstanceName = instance;
                    parms.AssociatedUserId = users;
                    var otherParams = string.Empty;
                    otherParams += "Id=" + data.Id;

                    parms.OtherParams = otherParams;

                    InstanceMessage flowInstance = _flowInstanceService.CreateInstance(parms);
                    if (flowInstance.Code == CodeEum.Fail)
                    {
                        throw new TipInfoException(flowInstance.Message);
                    }

                    data.FlowId = flowInstance.FlowId;


                }
                scope.SaveChanges();
                return true;
            }
        }

        public bool RejectWorkFlow(string id)
        {
            using (var scope = _dbContextScopeFactory.Create())
            {
                var db = scope.DbContexts.Get<WikeDbContext>();
                var data = db.Holidays.Load(id);
                data.FlowId = null;
                scope.SaveChanges();
                return true;
            }

        }

        public bool FinishWorkFlow(string id)
        {
            //TODO:处理自己的业务
            return true;
        }
    }
}
